Skip to main content

Deploy dwd-api-fastapi on the server (Docker)

Copy-paste runbook for msi-laptop-3. Goal: container listening on 127.0.0.1:8001, health check passing.

Full stack (FastAPI + MCP + Copilot): use [hydrotrek-dwd-suite/docker] — compose at /etc/dwd-stack/docker-compose.yml. This runbook covers FastAPI-only bootstrap or individual service clones under /opt/apis/.

Run as gqc over SSH unless noted. Use sudo where shown.


Before you start

From your Windows workstation, if not pushed yet:

cd "c:\jacob\admin\GQC Computers\MSI Laptop 3\repos\dwd-api-fastapi"
git add Dockerfile .dockerignore DOCKER.md
git commit -m "Add Docker support for on-prem deployment"
git push

Step 0 — Verify prerequisites

docker --version
docker compose version
id apisvc
groups # expect: ... apisvc ... docker ...

Step 1 — Clone or update source

API=dwd-api-fastapi
GITHUB_ORG=gqc
GITHUB_REPO=dwd-api-fastapi

# Skip clone if already present — use git pull instead
if [ ! -d /opt/apis/${API}/.git ]; then
git clone git@github.com-${API}:${GITHUB_ORG}/${GITHUB_REPO}.git \
/opt/apis/${API}
fi

cd /opt/apis/${API}
git pull

sudo chown -R apisvc:apisvc /opt/apis/${API}
sudo chmod -R g+rwX /opt/apis/${API}

# Must exist before build:
test -f /opt/apis/${API}/Dockerfile && echo "Dockerfile OK" || echo "MISSING Dockerfile — push to GitHub and git pull"

Step 2 — Host config directories

API=dwd-api-fastapi

sudo mkdir -p /etc/${API}
sudo chown root:apisvc /etc/${API}
sudo chmod 750 /etc/${API}

Step 3 — Secrets env file

API=dwd-api-fastapi

sudo cp /opt/apis/${API}/.env.example /etc/${API}/${API}.env
sudo chmod 640 /etc/${API}/${API}.env
sudo chown root:apisvc /etc/${API}/${API}.env
sudo nano /etc/${API}/${API}.env

Minimum for /health and basic operation: set DWD_API_BASE_URL to your ASP.NET v2 root (must end with /api/):

DWD_API_BASE_URL=https://your-aspnet-host.example.com/api/

Optional: OPENAI_API_KEY if you need POST /agent.


Step 4 — Production compose file

Standard pattern for full stack: hydrotrek-dwd-suite/docker/docker-compose.prod.yml/etc/dwd-stack/docker-compose.yml.

For FastAPI-only interim deploy, extract the dwd-api-fastapi service block from that file into /etc/dwd-api-fastapi/docker-compose.yml, or run the full stack compose.

After cloning or updating hydrotrek-dwd-suite:

sudo mkdir -p /etc/dwd-stack
sudo chown root:apisvc /etc/dwd-stack
sudo chmod 750 /etc/dwd-stack
sudo cp /opt/apis/hydrotrek-dwd-suite/docker/docker-compose.prod.yml /etc/dwd-stack/docker-compose.yml
sudo chmod 640 /etc/dwd-stack/docker-compose.yml
grep -E 'context:|env_file:|127.0.0.1' /etc/dwd-stack/docker-compose.yml

If the suite repo is not on the server yet, use templates/docker/hydrotrek-dwd-suite/docker-compose.prod.yml.

Stack orchestration lives in hydrotrek-dwd-suite only — not in individual API repos.


Step 5 — Build and start

First build may take several minutes (pip installs inside the image).

API=dwd-api-fastapi

cd /etc/${API}
sudo docker compose build
sudo docker compose up -d
sudo docker compose ps

Step 6 — Verify

curl -s http://127.0.0.1:8001/health
curl -s http://127.0.0.1:8001/ | head

Expected health JSON:

{"status":"ok","agent":{"enabled":false,...}}

Confirm binding is localhost only:

sudo ss -tlnp | grep 8001
# should show 127.0.0.1:8001

Logs:

cd /etc/dwd-api-fastapi
sudo docker compose logs -f --tail=50

Step 7 — systemd (start on boot)

Optional but recommended:

API=dwd-api-fastapi

sudo tee /etc/systemd/system/${API}.service > /dev/null << EOF
[Unit]
Description=${API} (Docker)
Documentation=file:///opt/apis/${API}/README.md
After=docker.service network-online.target
Requires=docker.service
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/etc/${API}

ExecStart=/usr/bin/docker compose -f /etc/${API}/docker-compose.yml up -d --remove-orphans
ExecStop=/usr/bin/docker compose -f /etc/${API}/docker-compose.yml down
ExecReload=/usr/bin/docker compose -f /etc/${API}/docker-compose.yml up -d --remove-orphans

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable ${API}
sudo systemctl start ${API}
sudo systemctl status ${API} --no-pager

Routine updates (after git push)

API=dwd-api-fastapi

cd /opt/apis/${API}
git pull
sudo chown -R apisvc:apisvc /opt/apis/${API}

cd /etc/${API}
sudo docker compose build
sudo docker compose up -d
curl -s http://127.0.0.1:8001/health

Troubleshooting

SymptomAction
MISSING DockerfilePush Docker files from workstation; git pull on server
Build fails on pipRead build output; check network from server
Container exitssudo docker compose logs
curl connection refusedsudo docker compose ps; rebuild and up
Permission denied on git pullConfirm groups includes apisvc
Port 8001 in usesudo ss -tlnp \| grep 8001

Restart from scratch:

cd /etc/dwd-api-fastapi
sudo docker compose down
sudo docker compose build --no-cache
sudo docker compose up -d

What comes next (not in this doc)

  1. Nginx LAN HTTP — 11-nginx-lan-setup.md
  2. SSL on Nginx (443) — uncomment block in LAN config when certs ready
  3. DNS subdomain → server Ethernet IP (server room)
  4. UFW — SSH on Wi‑Fi only; 80/443 on Ethernet — 09-wifi-and-ssh-network-setup.md

Checklist

  • git pull — Dockerfile present
  • /etc/dwd-api-fastapi/dwd-api-fastapi.envDWD_API_BASE_URL set
  • /etc/dwd-api-fastapi/docker-compose.yml in place
  • docker compose up -d — container running
  • curl http://127.0.0.1:8001/health"status":"ok"
  • 127.0.0.1:8001 only (not 0.0.0.0:8001)
  • systemd unit enabled (optional)